package cn.biplam.back.operator.ddl.db2sql;

import java.util.ArrayList;

import cn.biplam.back.operator.ddl.db2sql.dictionary.Dictionary;
import cn.biplam.back.operator.ddl.db2sql.dictionary.DictionaryFactory;
import cn.biplam.common.client.DataFilter;
import cn.biplam.common.client.Operator;
import cn.biplam.common.client.OperatorResult;
import cn.biplam.common.interfaces.DataOperator;
import cn.biplam.common.wrapper.ErrorMessage;

/**
 * 获取数据库表结构信息数据操作类<br>用于：数据库扫描
 * <ul> 功能：
 *  <li> 获取表信息
 *  <li> 获取表字段信息
 *  <li> 获取外键信息
 *  <li> 获取主键信息
 *  <li> 获取索引信息
 * </ul>
 * @author XiaoRuxing 2009-6-25下午06:39:28
 * @version 1.0
 */
public class DbInfo extends DataOperator{

	private Dictionary mDictionary;
	/**列 列名*/
	public static final String COLUMN_NAME = "COLUMN_NAME";
	/**列 数据类型，来自 java.sql.Types 的 SQL 类型*/
	public static final String COLUMN_DATA_TYPE = "DATA_TYPE";
	/**列 TYPE_NAME，数据源依赖的类型名称，对于 UDT，该类型名称是完全限定的*/
	public static final String COLUMN_TYPE_NAME = "TYPE_NAME";
	/**列 大小*/
	public static final String COLUMN_SIZE = "COLUMN_SIZE";
	/**列 小数部分的位数。对于 DECIMAL_DIGITS 不适用的数据类型，则返回 Null*/
	public static final String COLUMN_DECIMAL_DIGITS = "DECIMAL_DIGITS";
	/**列 基数（通常为 10 或 2）*/
	public static final String COLUMN_NUM_PREC_RADIX = "NUM_PREC_RADIX";
	/**列 是否允许使用 NULL*/
	public static final String COLUMN_NULLABLE = "NULLABLE";
	/**列 描述列的注释（可为 null*/
	public static final String COLUMN_COMMENTS = "REMARKS";
	/**列 该列的默认值，当值在单引号内时应被解释为一个字符串*/
	public static final String COLUMN_DEF = "COLUMN_DEF";
	/**列 ISO 规则用于确定列是否包括 null*/
	public static final String IS_NULLABLE = "IS_NULLABLE";
	/**表描述*/
	public static final String TABLE_COMMENTS = "TABLE_COMMENTS";
	/**表*/
	public static final String TABLE_CAT = "TABLE_CAT";
	/**表 用户*/
	public static final String TABLE_SCHEM = "TABLE_SCHEM";
	/**表 名*/
	public static final String TABLE_NAME = "TABLE_NAME";
	/**主键 名*/
	public static final String PK_NAME = "PK_NAME";
	/**主键 列名*/
	public static final String PK_COLUMN_NAME = "COLUMN_NAME";
	/**主键 列顺序*/
	public static final String PK_KEY_SEQ = "KEY_SEQ";
	/**外键 被导入的主键表名称*/
	public static final String FK_PKTABLE_NAME = "PKTABLE_NAME";
	/**外键 被导入的主键列名称*/
	public static final String FK_PKCOLUMN_NAME = "PKCOLUMN_NAME";
	/**外键 外键表名称*/
	public static final String FK_FKTABLE_NAME = "FKTABLE_NAME";
	/**外键 外键列名称*/
	public static final String FK_FKCOLUMN_NAME = "FKCOLUMN_NAME";
	/**外键 外键中的序列号（值 1 表示外键中的第一列，值 2 表示外键中的第二列*/
	public static final String FK_KEY_SEQ = "KEY_SEQ";
	/**外键 外键的名称（可为 null）*/
	public static final String FK_FK_NAME = "FK_NAME";
	/**外键 主键的名称（可为 null）*/
	public static final String FK_PK_NAME = "PK_NAME";
	/**索引 索引名称*/
	public static final String INDEX_INDEX_NAME  = "INDEX_NAME";
	/**索引 索引类型*/
	public static final String INDEX_TYPE  = "TYPE";
	/**索引 索引中的列序列号*/
	public static final String INDEX_ORDINAL_POSITION  = "ORDINAL_POSITION";
	/**索引 列名称*/
	public static final String INDEX_COLUMN_NAME  = "COLUMN_NAME";
	/**索引 列排序序列*/
	public static final String INDEX_ASC_OR_DESC  = "ASC_OR_DESC";	
	/**索引 是否唯一索引，0是，1否*/
	public static final String INDEX_NON_UNIQUE  = "NON_UNIQUE";

	/** 根据表名获取表元数据信息 
	 * <ul> 需要传入参数：
	 * <li> schema 用户
	 * <li> table_name 表名       (可选) 如果未指定获取指定用户下的所有的符合表范围的表
	 * <li> table_pattern 表名范围 (可选) 如果未指定则不对表范围过滤
	 * </ul>  
     */
	public static final String Get_Table = "30210101";

	/** 获取表字段
	 * <ul> 需要传入参数：
	 * <li> schema 用户
	 * <li> table_name 表名 
	 * </ul>  
     */
	public static final String Get_Fields = "30210102";

	/** 获取表主键
	 * <ul> 需要传入参数：
	 * <li> schema 用户
	 * <li> table_name 表名 
	 * </ul>  
     */
	public static final String Get_PK ="30210103";

	/** 获取表外键
	 * <ul> 需要传入参数：
	 * <li> schema 用户
	 * <li> table_name 表名 
	 * </ul>  
     */
	public static final String Get_FK = "30210104";

	/** 获取表索引
	 * <ul> 需要传入参数：
	 * <li> schema 用户
	 * <li> table_name 表名 
	 * </ul>  
     */
	public static final String Get_Index = "30210105";

	@Override
	protected OperatorResult _exchange() throws ErrorMessage {
		ArrayList<String> sql=new ArrayList<String>();
		
		if(this.opId.equals(Get_Table)){
			this.getTableInfo(sql, filter);
			return this.doing(sql, Operator_Type.Select);
		}else if(this.opId.equals(Get_Fields)){
			this.getColumns(sql, filter);
			return  this.doing(sql, Operator_Type.Select);
		}else if(this.opId.equals(Get_FK)){
			this.getFK(sql, filter);
			return  this.doing(sql, Operator_Type.Select);
		}else if(this.opId.equals(Get_PK)){
			this.getPK(sql, filter);
			return  this.doing(sql, Operator_Type.Select);
		}else if(this.opId.equals(Get_Index)){
			this.getIndexs(sql, filter);
			return  this.doing(sql, Operator_Type.Select);
		}else{
			throw new ErrorMessage("Data Operator id not found:"+ opId+" !");
		}
	}

	public DbInfo() throws ErrorMessage{
		super("db");
	}

	private void _init() throws ErrorMessage{
		mDictionary = DictionaryFactory.getInstance(this.dbResource);	
	}
	
	/** 根据表名获取表元数据信息 
	 * <ul> 需要传入参数：
	 * <li> schema 用户
	 * <li> table_name 表名       (可选) 如果未指定获取指定用户下的所有的符合表范围的表
	 * <li> table_pattern 表名范围 (可选) 如果未指定则不对表范围过滤
	 * </ul>  
	 * @throws ErrorMessage 
     */
	public void getTableInfo(ArrayList<String> sql,DataFilter filter) throws ErrorMessage {
		_init();
		filter.put(Operator.lineLimit, "10000");
		mDictionary.getTable(sql,filter);
	}

	/** 获取表字段
	 * <ul> 需要传入参数：
	 * <li> schema 用户
	 * <li> table_name 表名 
	 * </ul>  
	 * @throws ErrorMessage 
     */
	public void getColumns(ArrayList<String> sql,DataFilter filter) throws ErrorMessage {
		_init();
		filter.put(Operator.lineLimit, "10000");
		mDictionary.getColumns(sql,filter);
	}


	/** 获取表主键
	 * <ul> 需要传入参数：
	 * <li> schema 用户
	 * <li> table_name 表名 
	 * </ul>  
	 * @throws ErrorMessage 
     */
	public void getPK(ArrayList<String> sql,DataFilter filter) throws ErrorMessage {
		_init();
		filter.put(Operator.lineLimit, "10000");
		mDictionary.getPK(sql,filter);
	}

	/** 获取表外键
	 * <ul> 需要传入参数：
	 * <li> schema 用户
	 * <li> table_name 表名 
	 * </ul>  
	 * @throws ErrorMessage 
     */
	public void getFK(ArrayList<String> sql,DataFilter filter) throws ErrorMessage {
		_init();
		filter.put(Operator.lineLimit, "10000");
		mDictionary.getFK(sql,filter);
	}

	/** 获取表索引
	 * <ul> 需要传入参数：
	 * <li> schema 用户
	 * <li> table_name 表名 
	 * </ul>  
	 * @throws ErrorMessage 
     */
	public void getIndexs(ArrayList<String> sql,DataFilter filter) throws ErrorMessage {
		_init();
		filter.put(Operator.lineLimit, "10000");
		mDictionary.getIndexs(sql,filter);
	}
}
